<?php


namespace App\Kuafu\CustomerCoupon\Service;


use App\Exceptions\BaseException;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Coupon\Enum\CouponEnum;
use App\Kuafu\CustomerCoupon\Enum\CodeEnum;
use App\Kuafu\CustomerCoupon\Enum\CustomerCouponCodeEnum;
use App\Kuafu\CustomerCoupon\Exceptions\CustomerCouponException;
use App\Kuafu\CustomerCoupon\Model\CustomerCouponModel;
use App\Kuafu\Holiday\Service\HolidayService;
use App\Kuafu\Product\Model\Product;
use App\Kuafu\Shop\Service\ShopService;
use Illuminate\Support\Facades\Log;

class CustomerEnableCouponService extends BaseService
{
    /**
     * @var array 已使用的优惠券列表
     */
    private array $usedCoupons = [];

    /**
     * @var array 不可用优惠券列表
     */
    private array $canNotUseCouponList = [];

    /**
     * 可用优惠券列表
     * @var
     */
    private array $canUseCouponList = [];

    /**
     * @return array
     */
    public function getCanNotUseCouponList(): array
    {
        return $this->canNotUseCouponList;
    }

    /**
     * @param array $canNotUseCouponList
     */
    public function setCanNotUseCouponList(array $canNotUseCouponList): void
    {
        $this->canNotUseCouponList = $canNotUseCouponList;
    }

    /**
     * @return mixed
     */
    public function getCanUseCouponList(): array
    {
        return $this->canUseCouponList;
    }

    /**
     * @param mixed $canUseCouponList
     */
    public function setCanUseCouponList(array $canUseCouponList): void
    {
        $this->canUseCouponList = $canUseCouponList;
    }

    /**
     * @var array 商品分摊信息
     */
    private array $productList = [];

    private $userId;

    private $source;

    /**
     * @var int 已经优惠的金额
     */
    private $totalDiscount = 0;

    /**
     * @var int 已经抵扣的金额
     */
    private $totalCondition = 0;

    public function __construct($brandId, $shopId, $userId, $productList, $usedCouponList, $source)
    {
        parent::__construct($brandId, $shopId);
        $this->userId      = $userId;
        $this->usedCoupons = $usedCouponList;
        $this->productList = $productList;
        $this->source      = CodeEnum::CouponSourceChange($source);
        $this->checkUsedCoupon();
    }

    /**
     * 检查输入的优惠券
     */
    public function checkUsedCoupon()
    {
        //获取已经使用的优惠券列表
        $this->canUseCouponList = $this->usedCoupons;//可用优惠券列表
        $this->filterCustomerCoupon(CodeEnum::COUPON_INIT_TYPE_CHECK);
        $this->canUseCouponList = [];
    }

    /**
     * 获取用户所有优惠券信息
     * @param $userId
     */
    public function initCustomerCoupon()
    {
        // todo 菜品集合
        $productListCollection  = collect($this->productList);

        // todo 使用商品价格覆盖对应商品券的折扣金额
        $userCouponList         = CustomerCouponModel::userCoupons($this->userId, $this->shopId)->map(
            function (CustomerCouponModel $customerCouponModel) use ($productListCollection
            ) {
                if (
                    $customerCouponModel->couponType == CouponEnum::COUPON_TYPE_EXCHANGE
                    &&
                    $product = $productListCollection->where("productId", $customerCouponModel->canUseProduct)->first()
                ) {
                    $customerCouponModel->discount = $product["price"];
                }
                return $customerCouponModel;
            })->values();
        $this->canUseCouponList = $userCouponList->toArray();
        return $this;
    }

    /**
     *
     */
    public function filterCustomerCoupon($type = CodeEnum::COUPON_INIT_TYPE_SELECT)
    {

        //过滤不可用平台
        $this->filterCustomerCouponSource($type);

        //过滤有效期
        $this->filterCustomerCouponEffective($type);
        //过滤不可用店铺
        $this->filterCustomerCouponShop($type);
        //过滤活动叠加
//        $this->filterActivitySuperposition($type);
        //过滤优惠券不可用叠加
        $this->filterCustomerCouponSuperposition($type);

        //过滤使用超过最大限度
        $this->filterCustomerCouponUseMax($type);
        //过滤不可用日期
        $this->filterCustomerCouponDate($type);

        //过滤不可用时间
        $this->filterCustomerCouponTime($type);
        //过滤不可用产品
        $this->filterCustomerCouponProduct($type);
        //过滤金额不可用
        $this->filterCustomerCouponMoney($type);
        //过滤商品总价小于优惠券成本
        $this->filterCustomerCouponPrice($type);
        //重新组合返回数据
        $this->mergeCanUseCoupon();


        return $this;
    }

    public function mergeCanUseCoupon()
    {
        $usedCouponList         = $this->usedCoupons;
        $canUseCouponList       = $this->canUseCouponList;
        $canNotUseCouponList    = $this->canNotUseCouponList;
        $this->canUseCouponList = array_merge($usedCouponList, $canUseCouponList);
        $can                    = array_values(CommonService::arrayCustomerUnset($this->canUseCouponList,
            'couponCode'));
        $usedCouponListCodes    = array_column($usedCouponList, 'couponCode');
        foreach ($canNotUseCouponList as $key => $value) {
            if (in_array($value['couponCode'], $usedCouponListCodes)) {
                unset($canNotUseCouponList[$key]);
            }
        }
        $this->canUseCouponList    = $can;
        $this->canNotUseCouponList = array_values($canNotUseCouponList);
        return $this;
    }


    /**
     * 过滤优惠券有效期
     * @param $type
     * @return $this
     * @throws CustomerCouponException
     */
    public function filterCustomerCouponEffective($type): CustomerEnableCouponService
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $time                = time();
        foreach ($canUseCouponList as $key => $value) {
            //使用有效期  1 固定时间 2 相对时间
            if ($time <= $value['startAt'] || $time >= $value['endAt']) {
                Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                    ['msg' => '不在有效期范围内', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                    throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                } else {
                    $canNotUseCouponList[] = $value;
                    unset($canUseCouponList[$key]);
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤不可用平台
     * @param $type
     * @return CustomerEnableCouponService
     * @throws CustomerCouponException
     */
    public function filterCustomerCouponSource($type): CustomerEnableCouponService
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        foreach ($canUseCouponList as $key => $value) {
            if ($value['availableSource'] > 0) {
                $decodeRules = CommonService::decodeRules($value['availableSource']);
                if (!in_array($this->source, $decodeRules)) {
                    Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                        ['msg' => '平台不可用', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤活动不叠加
     * @param $type
     * @throws CustomerCouponException
     */
    public function filterActivitySuperposition($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $usedCoupons         = $this->usedCoupons;
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $activityIds         = array_unique(array_column($usedCoupons, 'activityId'));
        //判断已经选择的优惠券是否支持可叠加其他活动
        foreach ($canUseCouponList as $key => $value) {
            if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                if ($value['isSuperposeActivity'] == CouponEnum::SUPERPOSE_ACTIVITY_NO && count($activityIds) > 1) {
                    Log::info("获取可用优惠券列表错误-优惠券叠加", ['msg' => '活动不可叠加非法', 'userId' => $this->userId]);
                    throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                }
            } else {
                //判断已经使用的优惠券是否可以叠加活动
                foreach ($usedCoupons as $usedCoupon) {
                    if ($usedCoupon['isSuperposeActivity'] == CouponEnum::SUPERPOSE_ACTIVITY_NO) {
                        Log::info("获取可用优惠券列表错误-优惠券叠加", ['msg' => '活动不可叠加非法', 'userId' => $this->userId]);
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                        break;
                    }
                }
                if ($value['isSuperposeActivity'] == CouponEnum::SUPERPOSE_ACTIVITY_NO && count($activityIds) >= 1 && isset($canUseCouponList[$key])) {
                    Log::info("获取可用优惠券列表错误-优惠券叠加", ['msg' => '活动不可叠加非法', 'userId' => $this->userId]);
                    $canNotUseCouponList[] = $value;
                    unset($canUseCouponList[$key]);
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤优惠券不可叠加
     * @param $type
     * @return CustomerEnableCouponService
     * @throws CustomerCouponException
     */
    public function filterCustomerCouponSuperposition($type): CustomerEnableCouponService
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $usedCoupons         = $this->usedCoupons;//已经使用优惠券列表
        $couponIds           = array_unique(array_column($usedCoupons, 'couponCode'));
        $canNotUseCouponList = $this->canNotUseCouponList;

        $usedCouponsCollection = collect($usedCoupons);
        if ($type == CodeEnum::COUPON_INIT_TYPE_SELECT) {
            //todo 获取商品总价
            $totalPrice = 0;
            collect($this->productList)->each(function ($product) use (&$totalPrice) {
                $totalPrice += ($product["number"] * $product["price"]);
            });

            $exchangeCouponBaseQuery    = $usedCouponsCollection->where("couponType", CodeEnum::COUPON_TYPE_EXCHANGE);
            $nonExchangeCouponBaseQuery = $usedCouponsCollection->whereIn(
                "couponType", [CodeEnum::COUPON_TYPE_CASH, CodeEnum::COUPON_TYPE_DISCOUNT]
            );

            // todo 优惠券使用超过两张 || 商品券或非商品券超过一张  直接报错
            if ($usedCouponsCollection->count() > 2 || (clone $exchangeCouponBaseQuery)->count() > 1 || (clone $nonExchangeCouponBaseQuery)->count() > 1) {
                throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
            }

            // todo 判断是否存在商品券
            $existsExchangeCoupon = (clone $exchangeCouponBaseQuery)->first();
            // todo 判断是否存在非商品券
            $existsNonExchangeCoupon = (clone $nonExchangeCouponBaseQuery)->first();
            // todo 过滤掉互斥或不能叠加使用的券
            collect($canUseCouponList)->each(function ($canUseCoupon, $key) use (
                $totalPrice,
                $existsExchangeCoupon,
                $existsNonExchangeCoupon,
                &$canUseCouponList,
                &$canNotUseCouponList,
                $usedCouponsCollection
            ) {
                if ($existsExchangeCoupon) {
                    if ($canUseCoupon["couponType"] == CouponEnum::COUPON_TYPE_EXCHANGE) {
                        // ToDo 商品券已存在 -》 同类商品券置为不可用
                        array_push($canNotUseCouponList, $canUseCoupon);
                        unset($canUseCouponList[$key]);
                    } else {
                        // todo 商品券已存在 -》 非同类商品券判断门槛
                        $residualGrossPrice = bcsub($totalPrice, $existsExchangeCoupon["discount"]);
                        $can                = $residualGrossPrice > 0 && $residualGrossPrice >= $canUseCoupon["useCondition"];
                        if (!$can) {
                            array_push($canNotUseCouponList, $canUseCoupon);
                            unset($canUseCouponList[$key]);
                        }
                    }
                }


                if ($existsNonExchangeCoupon) {
                    if ($canUseCoupon["couponType"] != CouponEnum::COUPON_TYPE_EXCHANGE) {
                        // ToDo 非商品券已存在 -》 非商品券置为不可用
                        array_push($canNotUseCouponList, $canUseCoupon);
                        unset($canUseCouponList[$key]);
                    } else {
                        // todo 非商品券已存在 -》 商品券判断门槛
                        $residualGrossPrice = bcsub($totalPrice, $canUseCoupon["discount"]);
                        $can                = $residualGrossPrice > 0 && $residualGrossPrice >= $existsNonExchangeCoupon["useCondition"];
                        if (!$can) {
                            array_push($canNotUseCouponList, $canUseCoupon);
                            unset($canUseCouponList[$key]);
                        }
                    }
                }
            });
        }


        //判断已经选择的优惠券是否支持可叠加其他优惠券
//        foreach ($canUseCouponList as $key => $value) {
//            if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
//                if ($value['isSuperposeCoupon'] == CouponEnum::SUPERPOSE_COUPON_NO && count($couponIds) > 1) {
//                    Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
//                        ['msg' => '优惠券不可叠加', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
//                    throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
//                }
//            } else {
//                //判断已经使用的优惠券是否可以叠加活动
//                foreach ($usedCoupons as $usedCoupon) {
//                    if ($usedCoupon['isSuperposeCoupon'] == CouponEnum::SUPERPOSE_COUPON_NO) {
//                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
//                            ['msg' => '优惠券不可叠加', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
//                        $canNotUseCouponList[] = $value;
//                        unset($canUseCouponList[$key]);
//                        break;
//                    }
//                }
//                if ($value['isSuperposeCoupon'] == CouponEnum::SUPERPOSE_COUPON_NO && count($couponIds) >= 1 && isset($canUseCouponList[$key])) {
//                    Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
//                        ['msg' => '优惠券不可叠加', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
//                    $canNotUseCouponList[] = $value;
//                    unset($canUseCouponList[$key]);
//                }
//            }
//        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤最大使用张数
     * @return $this
     */
    public function filterCustomerCouponUseMax($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $usedCoupons         = $this->usedCoupons;//已经使用优惠券列表
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        foreach ($canUseCouponList as $key => $value) {
            if ($value['useMax'] > 0) {
                $usedCouponIds   = array_column($usedCoupons, 'couponId');
                $usedCountValues = array_count_values($usedCouponIds);
                if (isset($usedCountValues[$value['couponId']])) {
                    $usedCount = $usedCountValues[$value['couponId']];
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        if ($usedCount > $value['useMax']) {
                            Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                                [
                                    'msg'        => '超出可使用的最大张数',
                                    'userId'     => $this->userId,
                                    'couponCode' => $value['couponCode']
                                ]);
                            throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                        }
                    } else {
                        if ($usedCount >= $value['useMax']) {
                            Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                                [
                                    'msg'        => '超出可使用的最大张数',
                                    'userId'     => $this->userId,
                                    'couponCode' => $value['couponCode']
                                ]);
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤店铺
     * @param $shopId
     */
    public function filterCustomerCouponShop($type)
    {
        $canUseCouponList = $this->getCanUseCouponListByType($type);
        //获取店铺基本信息
        $shopInfo            = ShopService::getShopInfo($this->shopId);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        foreach ($canUseCouponList as $key => $value) {
            switch ($value['shopType']) {
                case CodeEnum::COUPON_SHOP_TYPE_JOIN:
                    //过滤非加盟
                    if ($shopInfo['type'] != CodeEnum::COUPON_SHOP_TYPE_JOIN) {
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}", [
                            'msg'        => '店铺不是非加盟，不可用',
                            'userId'     => $this->userId,
                            'shopId'     => $this->shopId,
                            'couponCode' => $value['couponCode']
                        ]);
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                    break;
                case CodeEnum::COUPON_SHOP_TYPE_DIRECTLY:
                    //t过滤非直营
                    if ($shopInfo['type'] != CodeEnum::COUPON_SHOP_TYPE_DIRECTLY) {
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}", [
                            'msg'        => '店铺不是非直营，不可用',
                            'userId'     => $this->userId,
                            'shopId'     => $this->shopId,
                            'couponCode' => $value['couponCode']
                        ]);
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                    break;
                case CodeEnum::COUPON_SHOP_TYPE_PART:
                    //过滤部分店铺
                    $shopIds = array_column($value['coupon_shop_rel'], 'shopId');
                    if (!in_array($this->shopId, $shopIds)) {
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}", [
                            'msg'        => '不在店铺可使用范围内',
                            'userId'     => $this->userId,
                            'shopId'     => $this->shopId,
                            'couponCode' => $value['couponCode']
                        ]);
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                    break;
                case CodeEnum::COUPON_SHOP_TYPE_ALl :
                    //全部 不做处理
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤可用商品
     */
    public function filterCustomerCouponProduct($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $productList         = $this->productList;
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        //获取产品列表的id集合
        $productListIds = array_column($productList, 'productId');
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['canUseProduct'])) {
                //todo 判断商品是可以用或者是不可以用
                if ($value['productUseType'] == CouponEnum::PRODUCT_USE_TYPE_NO) {
                    //不可使用时 先取出数据库不可适用列表
                    $notCanProductIds = explode(',', $value['canUseProduct']);
                    //比较两者差集就是可以使用的
                    $canUserProductIds = array_diff($productListIds, $notCanProductIds);
                } else {
                    $canUserProductIds = explode(',', $value['canUseProduct']);
                }
                //取交集，如果选择的商品不在可用商品范围内，过滤掉不可用的优惠券
                if (empty(array_intersect($productListIds, $canUserProductIds))) {
                    Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                        ['msg' => '选择的商品不可用', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤日期 周一到周六以及节假日
     */
    public function filterCustomerCouponDate($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        //获取星期 1-6表示周一到周六 0 表示周末
        $day  = date("w") != 0 ? date("w") : 7;
        $date = date("Ymd");
        //获取法定节假日
        $holidayConfigList = array_column(HolidayService::getHolidayConfigList(), 'holiday');
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['unableDate'])) {
                $canUseDay = explode(',', $value['unableDate']);
                //正常周末判断
                if ($day <= 7 && in_array($day, $canUseDay)) {
                    Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                        ['msg' => '日期不可用', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                        continue;
                    }
                }
                //判断法定节假日
                if (in_array(CodeEnum::COUPON_UNABLE_DATE_HOLIDAY, $canUseDay) && in_array($date, $holidayConfigList)) {
                    Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                        ['msg' => '节假日不可用', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤不可用时间
     * @param $type
     * @return $this
     * @throws CustomerCouponException
     */
    public function filterCustomerCouponTime($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        //获取当前时间
        $time = date('H:i:s');
        list($h, $m, $s) = explode(":", $time);
        $timeInt = ($h * 60 + $m) * 60 + $s;
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['unableTime'])) {
                $unableTime = json_decode($value['unableTime'], true);
                foreach ($unableTime as $item) {
                    if ($time >= $item['startAt'] && $time <= $item['endAt']) {
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                            ['msg' => '不在可用时间范围内', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤商品总金额可用
     *
     * @param $type
     * @return $this
     * @throws CustomerCouponException
     */
    public function filterCustomerCouponMoney($type): CustomerEnableCouponService
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $productList         = $this->productList;
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $productListIds      = array_column($productList, 'productId');

        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['useCondition'])) {
                // ToDo 可以使用的菜品列表集合
                $useProductIds = self::filterCanUseProductIds(
                    $value['productUseType'],
                    $productListIds,
                    $value['canUseProduct']
                );

                switch ($value["couponType"]) {
                    case CouponEnum::COUPON_TYPE_EXCHANGE:
                        // todo 兑换券 计算剔除可使用菜品后剩余总价是否满足门槛
                        $useProductId = current($useProductIds);
                        $totalMoney   = 0;
                        $decrease     = false;
                        collect($productList)->each(function ($product) use ($useProductId, &$totalMoney, &$decrease) {
                            if ($product["productId"] == $useProductId && $decrease == false) {
                                $product["number"] = $product["number"] - 1;
                                $decrease          = true;
                            }
                            $totalMoney += ((bcsub($product["number"], $product["freeNum"])) * $product["price"]);
                        });
                        break;
                    default:
                        // todo 折扣券&代金券  计算可使用商品总价是否满足门槛
                        $totalMoney = $this->sumProductTotalMoney($productList, $useProductIds);
                        break;
                }

                if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                    $totalCondition = ($value["couponType"] == CouponEnum::COUPON_TYPE_EXCHANGE ? 0 : $this->totalCondition);
                    //如果是检查
                    if ($totalMoney - $totalCondition < $value['useCondition']) {
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                            ['msg' => '商品金额不满足', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                        //如果剩余可抵扣金额小于当前券条件则报错
                        throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_USED_COUPON);
                    } else {
                        $this->totalCondition += ($value["couponType"] == CouponEnum::COUPON_TYPE_EXCHANGE ? 0 : $value['useCondition']);
                    }
                } else {
                    if ($totalMoney - $this->totalCondition < $value['useCondition']) {
                        //如果是选择，并且总金额减去总抵扣小小于当前券可抵扣
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                            ['msg' => '商品金额不满足', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤小于优惠券成本价
     * @param $type
     * @return $this
     * @throws CustomerCouponException
     */
    public function filterCustomerCouponPrice($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $productList         = $this->productList;
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $productListIds      = array_column($productList, 'productId');
        foreach ($canUseCouponList as $key => $value) {
            if ($value['costPrice'] > 0) {
                //可以使用的菜品列表集合
                $useProductIds = self::filterCanUseProductIds($value['productUseType'], $productListIds,
                    $value['canUseProduct']);
                $totalMoney    = $this->sumProductTotalMoney($productList, $useProductIds);
                if ($totalMoney < $value['costPrice']) {
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        //如果是检查
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                            ['msg' => '商品金额小于优惠券成本', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                        //如果剩余可抵扣金额小于当前券条件则报错
                        throw new CustomerCouponException(CustomerCouponCodeEnum::ERR_CUSTOMER_COST_PRICE);
                    } else {
                        //如果是选择，并且总金额减去总抵扣小小于当前券可抵扣
                        Log::info("获取可用优惠券列表错误-{$value['couponCode']}",
                            ['msg' => '商品金额小于优惠券成本', 'userId' => $this->userId, 'couponCode' => $value['couponCode']]);
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤可用商品列表
     * @param $type
     * @param $productListIds
     * @param $canUseProduct
     * @return array|mixed
     */
    public static function filterCanUseProductIds($type, $productListIds, $canUseProduct)
    {
        if (!empty($canUseProduct)) {
            if ($type == CouponEnum::PRODUCT_USE_TYPE_NO) {
                //不可使用时 先取出数据库不可适用列表
                $notCanProductIds = explode(',', $canUseProduct);
                //比较两者差集就是可以使用的
                $canUseProduct = array_diff($productListIds, $notCanProductIds);
            } else {
                $canUseProduct = explode(',', $canUseProduct);
            }
            //获取菜品交集 走到这一步肯定是有交集的
            return array_intersect($productListIds, $canUseProduct);
        } else {
            return [];
        }
    }

    /**
     * 获取可用优惠券列表 如果是检查则是用户使用的优惠券列表
     * @param $type
     * @return $this|array
     */
    public function getCanUseCouponListByType($type)
    {
        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
            $canUseCouponList = $this->usedCoupons;
        } else {
            $canUseCouponList = $this->canUseCouponList;//可用优惠券列表
            if (empty($canUseCouponList)) {
                return $canUseCouponList;
            }
        }
        return $canUseCouponList;
    }

    /**
     * 计算商品总金额
     * @param $productList
     * @param $intersect
     * @return float|int
     */
    public function sumProductTotalMoney($productList, $intersect)
    {
        $total = 0;
        if (empty($intersect)) {
            foreach ($productList as $value) {
                $total += $value['price'] * (bcsub($value["number"], $value["freeNum"]));
            }
        } else {
            foreach ($productList as $value) {
                if (in_array($value['productId'], $intersect)) {
                    $total += $value['price'] * (bcsub($value["number"], $value["freeNum"]));
                }
            }
        }
        return $total;
    }

    /**
     * 过滤已使用和可以使用的交集
     * @return $this
     */
    public function filterUsedCoupon($canUseCouponList)
    {
        $usedCouponList    = $this->usedCoupons;
        $usedCouponListIds = array_column($usedCouponList, 'couponCode');
        foreach ($canUseCouponList as $key => $value) {
            if (in_array($value['couponCode'], $usedCouponListIds)) {
                unset($canUseCouponList[$key]);
            }
        }
        $this->canUseCouponList = $canUseCouponList;
        return $this;
    }


}
